//============================================================================
// Name        : Buffer.cpp
// Author      : Artur Taranyuk
// Version     :
// Copyright   : Your copyright notice
// Description : Buffer#include <iostream>
//============================================================================

#include "Buffer.h"
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <malloc.h>
#include <errno.h>

using namespace std;

Buffer::Buffer(char *filename, char *output) {

	openCode = open(filename, O_SYNC, O_DIRECT);
	if (openCode > 0) {
		printf("Open succeeded.\n");
	} else {
		printf("Open failed.\n");
		switch(errno) {
			case EACCES: printf ("Permission denied.\n"); break;
			case EMFILE: printf ("No file handle available.\n"); break;
			case ENOENT: printf ("File or path not found.\n"); break;
			default: printf ("Unknown error.\n"); break;
		}
	}
	openCode1 = open(output, O_RDWR | O_CREAT, S_IRWXU);
	if (openCode1 > 0) {
		printf("Open succeeded.\n");
	} else {
		printf("Open failed.\n");
		switch(errno) {
			case EACCES: printf ("Permission denied.\n"); break;
			case EMFILE: printf ("No file handle available.\n"); break;
			case ENOENT: printf ("File or path not found.\n"); break;
			default: printf ("Unknown error.\n"); break;
		}
	}
	pagesize = getpagesize();
	alloc();

}
Buffer::~Buffer() {

}

void Buffer::alloc() {
	int fehler = posix_memalign((void**) &buffer1, pagesize, pagesize);
	if (fehler > 0) {
		printf("Buffer 1.\n");
	}
	int fehler2 = posix_memalign((void**) &buffer2, pagesize, pagesize);
	if (fehler2 > 0) {
		printf("Buffer 2.\n");
	}
	int fehler3 = posix_memalign((void**) &outputBuffer, pagesize, pagesize);
	if (fehler3 > 0) {
		printf("outputBuffer.\n");
	}
	loadPuffer1();
	next = buffer1;
	base = buffer1;
	InputNext = outputBuffer;
	count = 0;
}

char Buffer::getchar() {

	if (*next == EOF) {
		if (buffer1[4095] == EOF) {
			cout << "2";
			loadPuffer2();
			next = buffer2;
			buffer1[4095] = 0;
		} else if (buffer2[4095] == EOF) {
			loadPuffer1();
			next = buffer1;
			buffer2[4095] = 0;
		} else {
			writeFile();
			exit(0);
		}
	}
	output = *next;
	next++;
	//cout<<output;
	return output;
}

void Buffer::ungetchar(int count) {
	while (count>0){
	next--;
	if (next == &buffer2[0]) {
		next = &buffer1[4094];
		buffer1[4095]=EOF;
	} else if (next == &buffer1[0]) {
		next = &buffer2[4094];
		buffer2[4095]=EOF;
	}
	next--;
	count--;
	}
}

void Buffer::loadPuffer1() {
	int Actual = 1;
	int Max = 4095;
	Actual = read(openCode, buffer1, Max);
	if (Actual == 4095) {
		buffer1[4095] = EOF;
	}
	if ((Actual < Max) & (Actual > 0)) {
		buffer1[Actual] = EOF;
		printf("An incomplete record was read Puffer 1.\n");

	}
}

void Buffer::loadPuffer2() {
	int Actual = 1;
	int Max = 4095;
	Actual = read(openCode, buffer2, Max);
	if (Actual == 4095) {
		buffer2[4095] = EOF;
	}
	if ((Actual < Max) & (Actual > 0)) {
		buffer2[Actual] = EOF;
		printf("An incomplete record was read Puffer 2.\n");
	}
}

void Buffer::lexemAcceped() {
	next++;
	base = next;
}

void Buffer::putChar(char *symbol) {

	*InputNext = *symbol;
	cout << *InputNext;
	InputNext++;
	count++;
	if (count == 4096) {
		writeFile();
	}
}

void Buffer::writeFile() {
	int more = 1;
	int maximum = 4096;
	more = write(openCode1, outputBuffer, count);
	cout << more;
	if (more < maximum) {
		printf("An incomplete record was written.\n");
	}
	InputNext = outputBuffer;
	count = 0;
}

void Buffer::close(){
	writeFile();
	exit(0);
}
